from Bases import setID
from Bases import OSCBaseObject

class GroupBase(OSCBaseObject):
    _saved_attributes = ['base_class', 'id', 'name', 'keep_when_empty', 'membership_lock']
    _Properties = {'name':dict(type=str)}
    def __init__(self, **kwargs):
        self.base_class = 'Group'
        self.members = {}
        #self._name = None
        self._membership_lock = None
        self._name_set_by_osc = True
        super(GroupBase, self).__init__(**kwargs)
        self.users = set()
        self.register_signal('member_update', 'no_users', 'no_members')
        if 'deserialize' not in kwargs:
            self.id = setID(kwargs.get('id'))
            self.name = kwargs.get('name', self.__class__.__name__)
            self.keep_when_empty = kwargs.get('keep_when_empty', False)
            self.membership_lock = kwargs.get('membership_lock', False)
        self.parent_group = kwargs.get('parent_group')
        if self.parent_group is None:
            self.valid = self.search_for_members(**kwargs)
        else:
            self.valid = False
        self.add_osc_handler(callbacks={'name-change':self.on_osc_name_change})
        
        self.bind(name=self.on_name_set)
        
    def on_name_set(self, **kwargs):
        name = kwargs.get('value')
        if self.osc_enabled and not self._name_set_by_osc:
            self.osc_node.send_message(address='name-change', value=name)
        self._name_set_by_osc = False
        self.set_osc_address(name)
        #self.emit('property_changed', obj=self, property='name')
        
#    @property
#    def name(self):
#        return self._name
#    @name.setter
#    def name(self, value):
#        if self.osc_enabled and not self._name_set_by_osc:
#            self.osc_node.send_message(address='name-change', value=value)
#        self._name_set_by_osc = False
#        self.set_osc_address(value)
#        self._name = value
#        self.emit('property_changed', obj=self, property='name')
    
    @property
    def membership_lock(self):
        return self._membership_lock
    @membership_lock.setter
    def membership_lock(self, value):
        self._membership_lock = value
        
    def unlink(self):
        for member in self.members.itervalues():
            member.del_user(self)
    def add_user(self, user):
        self.users.add(user)
    def del_user(self, user):
        self.users.discard(user)
        if len(self.users) == 0 and not self.keep_when_empty:
            self.emit('no_users', Group=self)
    def add_member(self, **kwargs):
        if not self.membership_lock:
            for key, val in kwargs.iteritems():
                if key not in self.members:
                    self.members.update({key:val})
                    if hasattr(val, 'add_user'):
                        val.add_user(self)
                        if isinstance(val, GroupBase):
                            val.connect('no_users', self.on_member_no_users)
                            val.connect('no_members', self.on_member_no_members)
                    self.emit('member_update', Group=self, new=val)
            
    def del_member(self, key):
        if not self.membership_lock and key in self.members:
            member = self.members[key]
            if hasattr(member, 'del_user'):
                member.del_user(self)
            del self.members[key]
            self.emit('member_update', Group=self, deleted=member)
            if len(self.members) == 0 and not self.keep_when_empty:
                self.emit('no_members', Group=self)
        #print 'key not found', key, self
    def search_for_members(self, **kwargs):
        pass
        
    def on_member_no_users(self, **kwargs):
        Group = kwargs.get('Group')
        print 'group %s, no users' % (Group)
    def on_member_no_members(self, **kwargs):
        Group = kwargs.get('Group')
        print 'group %s no members'
        if Group and Group.id in self.members:
            self.del_member(Group.id)
            
    def on_osc_name_change(self, **kwargs):
        value = kwargs.get('values')[0]
        if value != self.name:
            self._name_set_by_osc = True
            self.name = value
            
    def search_for_obj(self, objkey):
        if objkey == self.id:
            return self
        if objkey in self.members:
            return self.members[objkey]
        for m in self.members.itervalues():
            if getattr(m, 'base_class') == 'Group':
                result = m.search_for_obj(objkey)
                if result:
                    return result
        return False
        